using System.Collections.Generic;
using Function.SkillEditor.Runtime;
using SCore.Function.Fixed;
using SCore.Util;
using UnityEngine;
using UnityEngine.AddressableAssets;

namespace Function.SkillEditor.Runtime
{
    public class SkillRunLogic : Singleton<SkillRunLogic>
    {
        private Dictionary<int, SkillRunLine> _skillMap = new Dictionary<int, SkillRunLine>();

        /// <summary>
        /// 创建配置文件
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public SkillRunLine CreateSkillRunLine(int id, SkillEntityData skillEntityData)
        {
            if (!_skillMap.TryGetValue(id, out var skillRunLine))
            {
                var loadAsset = Addressables.LoadAssetAsync<SkillRunLine>($"{id}.asset");
                loadAsset.WaitForCompletion();
                skillRunLine = loadAsset.Result;
                _skillMap.Add(id, skillRunLine);
            }

            return CopySkillRunLine(skillRunLine, skillEntityData);
        }

        /// <summary>
        /// copy 全新的实例的配置文件
        /// </summary>
        /// <param name="skillRunLine"></param>
        /// <returns></returns>
        private SkillRunLine CopySkillRunLine(SkillRunLine skillRunLine, SkillEntityData skillEntityData)
        {
            //copy skillRunLine对象
            SkillRunLine copyRunLine = Object.Instantiate(skillRunLine);
            var skillTracks = copyRunLine._skillTracks;
            Dictionary<SkillClip, SkillClip> skillClipMap = new Dictionary<SkillClip, SkillClip>();
            for (int offsetTrack = skillTracks.Count - 1; offsetTrack >= 0; offsetTrack--)
            {
                var eachTrack = Object.Instantiate(copyRunLine._skillTracks[offsetTrack]);
                copyRunLine._skillTracks[offsetTrack] = eachTrack;
                var eachClips = eachTrack.GetClips();
                for (int offsetClip = eachClips.Count - 1; offsetClip >= 0; offsetClip--)
                {
                    var eachClip = eachClips[offsetClip];
                    var copyClip = Object.Instantiate(eachClip);
                    copyClip.Configure(skillEntityData);
                    eachClips[offsetClip] = copyClip;
                    skillClipMap.Add(eachClip, copyClip);
                }
            }

            //clip嵌套clip的引用的时候 需要对嵌套的对象进行覆盖为clone 的对象
            for (int offsetTrack = skillTracks.Count - 1; offsetTrack >= 0; offsetTrack--)
            {
                var skillTrack = skillTracks[offsetTrack];
                if (skillTrack.Is<SkillBuffTrack>())
                {
                    var eachClips = skillTrack.GetClips();
                    for (int offsetClip = eachClips.Count - 1; offsetClip >= 0; offsetClip--)
                    {
                        SkillBuffClip skillClip = eachClips[offsetClip].As<SkillBuffClip>();
                        List<SkillTriggerClip> saveClips = new List<SkillTriggerClip>();
                        foreach (var triggerClip in skillClip._triggers)
                        {
                            saveClips.Add(skillClipMap[triggerClip] as SkillTriggerClip);
                        }

                        skillClip._triggers = saveClips;
                    }
                }
            }

            return copyRunLine;
        }

        /// <summary>
        /// 预加载
        /// </summary>
        /// <param name="skillRunLine"></param>
        public void PreLoadAssets(SkillRunLine skillRunLine)
        {
        }
    }

    /// <summary>
    /// 实体数据
    /// </summary>
    public class SkillEntityData
    {
        public int _entityId;
    }


    /// <summary>
    /// 运行器 挂载到对应的对象上
    /// </summary>
    public class SkillRunLineLoader
    {
        /// <summary>
        /// 当前执行的帧数
        /// </summary>
        private int _runFrame = 0;

        /// <summary>
        /// 实体id
        /// </summary>
        private SkillEntityData _skillEntityData;

        /// <summary>
        /// 运行的line
        /// </summary>
        private List<SkillRunLine> _skillRunLines = new List<SkillRunLine>(10);

        public SkillRunLineLoader(SkillEntityData skillEntityData)
        {
            _skillEntityData = skillEntityData;
        }

        public void AddSkillRunLines(int id)
        {
            var skillRunLine = SkillRunLogic.Instance.CreateSkillRunLine(id, _skillEntityData);
            _skillRunLines.Add(skillRunLine);
        }

        public void Tick(fp dt)
        {
            //tick
            for (int offset = _skillRunLines.Count - 1; offset >= 0; offset--)
            {
                if (_skillRunLines[offset].Finish())
                {
                    _skillRunLines.RemoveAt(offset);
                    continue;
                }

                _skillRunLines[offset].Tick(dt);
            }

            _runFrame += 1;
        }
    }
}